from flask import Blueprint, current_app, render_template, request, jsonify, redirect, url_for, flash
from flask_login import login_required, current_user
from ..models.database import db
from ..models.models import Student, Course, Grade, Class, College, Registration, Teacher
from sqlalchemy import func
import os
from werkzeug.utils import secure_filename
from functools import wraps

bp = Blueprint('student', __name__, url_prefix='/student')

"""
学生端路由模块

提供学生用户相关的功能，包括：
1. 页面路由：
   - /: 学生首页
   - /analysis: 个人成绩分析页面
   - /courses: 课程信息页面
   - /grades: 成绩查询页面
   - /profile: 个人信息页面
2. API路由：
   - GET /api/grades: 获取成绩列表，支持按学期筛选
   - GET /api/courses: 获取课程列表，支持按学期筛选
   - POST /api/profile: 更新个人信息
   - POST /api/upload-avatar: 上传头像

所有路由都需要学生登录权限，使用login_required装饰器进行保护。
部分路由使用add_registration装饰器自动添加注册信息。
"""

# 注册信息装饰器，始终用student_number作为user_id
# -----------------------------------------------
def add_registration(f):
    """
    注册信息装饰器
    
    自动将学生的注册信息添加到路由函数的参数中。
    该装饰器会：
    1. 查询当前学生的注册信息（使用student_number作为user_id）
    2. 将注册信息作为参数传递给被装饰的函数
    
    Args:
        f (function): 需要装饰的路由函数
        
    Returns:
        function: 装饰后的函数，增加了registration参数
    """
    @wraps(f)
    def decorated_function(*args, **kwargs):
        registration = Registration.query.filter_by(
            user_type='student',
            user_id=str(current_user.student_number)
        ).first()
        return f(registration=registration, *args, **kwargs)
    return decorated_function

# 学生首页
@bp.route('/')
@login_required
@add_registration
def index(registration):
    """
    学生首页路由
    
    显示学生的首页信息，需要：
    1. 学生登录权限
    2. 注册信息
    
    Args:
        registration: 学生注册信息，由add_registration装饰器提供
        
    Returns:
        str: 渲染后的学生首页HTML
    """
    return render_template('student/index.html', registration=registration)

# 个人成绩分析页面
# -----------------------------------------------
@bp.route('/analysis')
@login_required
@add_registration
def analysis(registration):
    """
    个人成绩分析页面路由
    
    显示学生的成绩分析数据，包括：
    1. 基本统计信息：
       - 平均分
       - 最高分
       - 最低分
       - 课程总数
    2. 成绩分布：
       - 90分以上
       - 80-89分
       - 70-79分
       - 60-69分
       - 60分以下
    3. 课程成绩对比
    4. 学期成绩趋势
    
    所有查询均使用student_number作为唯一标识。
    
    Args:
        registration: 学生注册信息，由add_registration装饰器提供
        
    Returns:
        str: 渲染后的成绩分析页面HTML
    """
    if not isinstance(current_user, Student):
        return redirect(url_for('auth.login'))
    # 获取学生信息（用student_number）
    student = Student.query.filter_by(student_number=current_user.student_number).first()
    # 获取所有学期
    semesters = db.session.query(Grade.semester)\
        .filter_by(student_number=current_user.student_number)\
        .distinct()\
        .order_by(Grade.semester)\
        .all()
    semester_labels = [semester[0] for semester in semesters]
    # 获取所有成绩数据（用于前端筛选）
    all_grades = db.session.query(
        Grade.total_score,
        Course.course_name,
        Grade.semester
    ).join(Course, Course.course_id == Grade.course_id)\
        .filter(Grade.student_number == current_user.student_number)\
        .all()
    all_grades = [{
        'total_score': float(grade[0]),
        'course_name': grade[1],
        'semester': grade[2]
    } for grade in all_grades]
    # 计算平均分
    average_grade = db.session.query(func.avg(Grade.total_score))\
        .filter_by(student_number=current_user.student_number)\
        .scalar() or 0
    # 获取最高分
    highest_grade = db.session.query(func.max(Grade.total_score))\
        .filter_by(student_number=current_user.student_number)\
        .scalar() or 0
    # 获取最低分
    lowest_grade = db.session.query(func.min(Grade.total_score))\
        .filter_by(student_number=current_user.student_number)\
        .scalar() or 0
    # 获取课程数
    course_count = db.session.query(func.count(Grade.grade_id))\
        .filter_by(student_number=current_user.student_number)\
        .scalar() or 0
    # 获取成绩分布
    grade_distribution = [
        db.session.query(func.count(Grade.grade_id))\
            .filter_by(student_number=current_user.student_number)\
            .filter(Grade.total_score >= 90)\
            .scalar() or 0,
        db.session.query(func.count(Grade.grade_id))\
            .filter_by(student_number=current_user.student_number)\
            .filter(Grade.total_score >= 80, Grade.total_score < 90)\
            .scalar() or 0,
        db.session.query(func.count(Grade.grade_id))\
            .filter_by(student_number=current_user.student_number)\
            .filter(Grade.total_score >= 70, Grade.total_score < 80)\
            .scalar() or 0,
        db.session.query(func.count(Grade.grade_id))\
            .filter_by(student_number=current_user.student_number)\
            .filter(Grade.total_score >= 60, Grade.total_score < 70)\
            .scalar() or 0,
        db.session.query(func.count(Grade.grade_id))\
            .filter_by(student_number=current_user.student_number)\
            .filter(Grade.total_score < 60)\
            .scalar() or 0
    ]
    # 获取课程成绩对比数据
    course_data = db.session.query(Course.course_name, Grade.total_score)\
        .join(Grade, Grade.course_id == Course.course_id)\
        .filter(Grade.student_number == current_user.student_number)\
        .order_by(Grade.total_score.desc())\
        .all()
    course_names = [course[0] for course in course_data]
    course_grades = [float(course[1]) for course in course_data]
    # 获取成绩趋势数据
    semester_data = db.session.query(Grade.semester, func.avg(Grade.total_score))\
        .filter_by(student_number=current_user.student_number)\
        .group_by(Grade.semester)\
        .order_by(Grade.semester)\
        .all()
    semester_labels = [semester[0] for semester in semester_data]
    semester_averages = [round(float(semester[1]), 2) for semester in semester_data]
    return render_template('student/analysis.html',
                         average_grade=round(average_grade, 2),
                         highest_grade=round(highest_grade, 2),
                         lowest_grade=round(lowest_grade, 2),
                         course_count=course_count,
                         grade_distribution=grade_distribution,
                         course_names=course_names,
                         course_grades=course_grades,
                         semester_labels=semester_labels,
                         semester_averages=semester_averages,
                         all_grades=all_grades,
                         registration=registration)

# 课程信息页面
# -----------------------------------------------
@bp.route('/courses')
@login_required
@add_registration
def courses(registration):
    """
    课程信息页面路由
    
    显示学生的课程信息，包括：
    1. 所有已修课程列表
    2. 课程总数统计
    3. 总学分统计
    4. 学期列表
    
    所有查询均使用student_number作为唯一标识。
    
    Args:
        registration: 学生注册信息，由add_registration装饰器提供
        
    Returns:
        str: 渲染后的课程信息页面HTML
    """
    if not isinstance(current_user, Student):
        return redirect(url_for('auth.login'))
    # 获取所有学期
    semesters = db.session.query(Course.semester)\
        .join(Grade, Grade.course_id == Course.course_id)\
        .filter(Grade.student_number == current_user.student_number)\
        .distinct()\
        .order_by(Course.semester)\
        .all()
    semester_labels = [semester[0] for semester in semesters]
    # 获取学生的所有课程及教师名
    courses = db.session.query(Course, Teacher.name)\
        .join(Grade, Grade.course_id == Course.course_id)\
        .join(Teacher, Teacher.teacher_id == Grade.teacher_id)\
        .filter(Grade.student_number == current_user.student_number)\
        .all()
    course_list = [{
        'course_id': course.course_id,
        'course_name': course.course_name,
        'credits': course.credits,
        'teacher_name': teacher_name,
        'semester': course.semester
    } for course, teacher_name in courses]
    # 计算总课程数
    total_courses = len(course_list)
    # 计算总学分
    total_credits = db.session.query(func.sum(Course.credits))\
        .join(Grade, Grade.course_id == Course.course_id)\
        .filter(Grade.student_number == current_user.student_number)\
        .scalar() or 0
    return render_template('student/courses.html',
                         courses=course_list,
                         total_courses=total_courses,
                         total_credits=total_credits,
                         semester_labels=semester_labels,
                         registration=registration)

# 成绩查询页面
# -----------------------------------------------
@bp.route('/grades')
@login_required
@add_registration
def grades(registration):
    """
    成绩查询页面路由
    
    显示学生的成绩信息，包括：
    1. 所有课程成绩列表
    2. 总学分统计
    3. 已通过课程数统计
    4. 学期列表
    
    所有查询均使用student_number作为唯一标识。
    
    Args:
        registration: 学生注册信息，由add_registration装饰器提供
        
    Returns:
        str: 渲染后的成绩查询页面HTML
    """
    if not isinstance(current_user, Student):
        flash('您没有权限访问此页面', 'error')
        return redirect(url_for('main.index'))
    # 获取所有学期标签
    semester_labels = db.session.query(Grade.semester)\
        .filter(Grade.student_number == current_user.student_number)\
        .distinct()\
        .order_by(Grade.semester.desc())\
        .all()
    semester_labels = [label[0] for label in semester_labels]
    # 获取所有成绩
    grades = Grade.query.filter_by(student_number=current_user.student_number).all()
    # 计算总学分和已通过课程数
    total_credits = sum(grade.course.credits for grade in grades)
    passed_courses = sum(1 for grade in grades if grade.total_score >= 60)
    return render_template('student/grades.html',
                         grades=grades,
                         total_credits=total_credits,
                         passed_courses=passed_courses,
                         semester_labels=semester_labels,
                         registration=registration)

# API：获取成绩
# -----------------------------------------------
@bp.route('/api/grades')
@login_required
def get_grades():
    """
    获取成绩列表的API
    
    支持按学期筛选成绩，返回：
    - 课程ID和名称
    - 学分
    - 平时成绩
    - 期末成绩
    - 总评成绩
    - 学期
    
    所有查询均使用student_number作为唯一标识。
    
    Query Parameters:
        semester (str): 学期，用于筛选特定学期的成绩
        
    Returns:
        dict: JSON响应，包含成绩列表
    """
    if not isinstance(current_user, Student):
        return jsonify({'error': 'Unauthorized'}), 403
    semester = request.args.get('semester')
    query = Grade.query.filter_by(student_number=current_user.student_number)
    if semester:
        query = query.filter_by(semester=semester)
    grades = query.all()
    return jsonify([{
        'course_id': grade.course.course_id,
        'course_name': grade.course.course_name,
        'credits': float(grade.course.credits),
        'regular_score': grade.regular_score,
        'final_score': grade.final_score,
        'total_score': grade.total_score,
        'semester': grade.semester
    } for grade in grades])

# API：获取课程
# -----------------------------------------------
@bp.route('/api/courses')
@login_required
def get_courses():
    """
    获取课程列表的API
    
    支持按学期筛选课程，返回：
    - 课程ID和名称
    - 学分
    - 学期
    - 教师姓名
    
    所有查询均使用student_number作为唯一标识。
    
    Query Parameters:
        semester (str): 学期，用于筛选特定学期的课程
        
    Returns:
        dict: JSON响应，包含课程列表
    """
    if not isinstance(current_user, Student):
        return jsonify({'error': 'Unauthorized'}), 401
    semester = request.args.get('semester', '')
    query = db.session.query(Course, Teacher.name)\
        .join(Grade, Grade.course_id == Course.course_id)\
        .join(Teacher, Teacher.teacher_id == Grade.teacher_id)\
        .filter(Grade.student_number == current_user.student_number)
    if semester:
        query = query.filter(Grade.semester == semester)
    results = query.all()
    return jsonify([{
        'course_id': course.course_id,
        'course_name': course.course_name,
        'credits': float(course.credits),
        'semester': course.semester,
        'teacher_name': teacher_name
    } for course, teacher_name in results])

# 个人信息页面，所有查询均用student_number
# -----------------------------------------------
@bp.route('/profile')
@login_required
@add_registration
def profile(registration):
    """
    个人信息页面路由
    
    显示学生的个人信息，包括：
    1. 基本信息（学号、姓名、性别等）
    2. 班级信息（班级名称、年级）
    3. 学院信息
    4. 成绩信息（课程名称、平时成绩、期末成绩、总评成绩）
    
    所有查询均使用student_number作为唯一标识。
    如果任何信息不存在，会显示相应的错误提示。
    
    Args:
        registration: 学生注册信息，由add_registration装饰器提供
        
    Returns:
        str: 渲染后的个人信息页面HTML，包含：
            - profile: 包含学生基本信息和成绩信息的字典
            - registration: 注册信息
    """
    try:
        # 获取学生信息（用student_number）
        student = Student.query.filter_by(student_number=current_user.student_number).first()
        if not student:
            flash('学生信息不存在，请联系管理员', 'error')
            return render_template('student/profile.html', profile=None, registration=registration)
        # 获取班级信息
        class_info = Class.query.get(student.class_id)
        if not class_info:
            flash('班级信息不存在，请联系管理员', 'error')
            return render_template('student/profile.html', profile=None, registration=registration)
        # 获取学院信息
        college = College.query.get(class_info.college_id)
        if not college:
            flash('学院信息不存在，请联系管理员', 'error')
            return render_template('student/profile.html', profile=None, registration=registration)
        # 获取成绩信息
        grades = Grade.query.filter_by(student_number=student.student_number).all()
        grade_list = []
        for grade in grades:
            course = Course.query.get(grade.course_id)
            if course:
                grade_list.append({
                    'course_name': course.course_name,
                    'regular_score': grade.regular_score,
                    'final_score': grade.final_score,
                    'total_score': grade.total_score
                })
        # 组装profile数据
        profile_data = {
            'student': {
                'student_id': student.student_number,
                'name': student.name,
                'gender': student.gender,
                'class_name': class_info.class_name,
                'college_name': college.college_name,
                'grade_year': getattr(class_info, 'grade_year', '')
            },
            'grades': grade_list
        }
        return render_template('student/profile.html', profile=profile_data, registration=registration)
    except Exception as e:
        flash('获取个人信息失败，请稍后重试', 'error')
        return render_template('student/profile.html', profile=None, registration=registration)

# API：更新个人信息
# -----------------------------------------------
@bp.route('/api/profile', methods=['POST'])
@login_required
def update_profile():
    """
    更新个人信息的API
    
    允许学生更新以下信息：
    - 邮箱
    - 手机号码
    - 密码（可选）
    
    所有查询均使用student_number作为唯一标识。
    
    Request Body:
        {
            'email': str,     # 新的邮箱地址
            'phone': str,     # 新的手机号码
            'password': str   # 新的密码（可选）
        }
        
    Returns:
        dict: JSON响应，包含：
            - success: 请求是否成功
            - message: 成功或错误信息
    """
    data = request.get_json()
    try:
        registration = Registration.query.filter_by(
            user_type='student',
            user_id=str(current_user.student_number)
        ).first()
        if not registration:
            return jsonify({'success': False, 'message': '未找到注册信息'}), 404
        if 'email' in data:
            registration.email = data['email']
        if 'phone' in data:
            registration.phone = data['phone']
        if data.get('password'):
            registration.set_password(data['password'])
        db.session.commit()
        return jsonify({'success': True, 'message': '个人信息更新成功'})
    except Exception as e:
        db.session.rollback()
        return jsonify({'success': False, 'message': str(e)}), 400